﻿using System.Text;
using System.Text.RegularExpressions;
using System.Web.Routing;
using System.Collections;
using System.Collections.Generic;


namespace System.Web.Mvc
{
    public static class PagerHelper
    {
        private const int defaultDisplayCount = 7;

        #region HtmlHelper Extensions

        /// <summary>
        /// Pager Helper Extensions
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">页面显示的数据条目</param>
        /// <param name="totalCount">总记录数</param>
        /// <param name="toDisplayCount">Helper要显示的页数</param>
        /// <returns></returns>
        public static string Pager(this HtmlHelper htmlHelper, int currentPage, int pageSize, int totalCount, int toDisplayCount)
        {
            RenderPager pager = new RenderPager(htmlHelper.ViewContext, currentPage, pageSize, totalCount, toDisplayCount);
            return pager.RenderHTML();
        }

        /// <summary>
        /// Pager Helper Extensions
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">页面显示的数据条目</param>
        /// <param name="totalCount">总记录数</param>
        /// <param name="toDisplayCount">Helper要显示的页数</param>
        /// <returns></returns>
        public static string Pager(this HtmlHelper htmlHelper, int currentPage, int pageSize, int totalCount, int toDisplayCount, object routeValues)
        {
            RenderPager pager = new RenderPager(htmlHelper.ViewContext, currentPage, pageSize, totalCount, toDisplayCount, routeValues);
            return pager.RenderHTML();
        }

        /// <summary>
        /// Pager Helper Extensions
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">页面显示的数据条目</param>
        /// <param name="totalCount">总记录数</param>
        /// <returns></returns>
        public static string Pager(this HtmlHelper htmlHelper, int currentPage, int pageSize, int totalCount)
        {
            RenderPager pager = new RenderPager(htmlHelper.ViewContext, currentPage, pageSize, totalCount, defaultDisplayCount);
            return pager.RenderHTML();
        }

        /// <summary>
        /// Pager Helper Extensions
        /// </summary>
        /// <param name="htmlHelper"></param>
        /// <param name="currentPage">当前页码</param>
        /// <param name="pageSize">页面显示的数据条目</param>
        /// <param name="totalCount">总记录数</param>
        /// <returns></returns>
        public static string Pager(this HtmlHelper htmlHelper, int currentPage, int pageSize, int totalCount, object routeValues)
        {
            RenderPager pager = new RenderPager(htmlHelper.ViewContext, currentPage, pageSize, totalCount, defaultDisplayCount, routeValues);
            return pager.RenderHTML();
        }

        #endregion
    }

    public class RenderPager
    {
        #region 字段
        /// <summary>
        /// 当前页面的ViewContext
        /// </summary>
        private ViewContext viewContext;
        /// <summary>
        /// 当前页码
        /// </summary>
        private readonly int currentPage;
        /// <summary>
        /// 页面要显示的数据条数
        /// </summary>
        private readonly int pageSize;
        /// <summary>
        /// 总的记录数
        /// </summary>
        private readonly int totalCount;
        /// <summary>
        /// Pager Helper 要显示的页数
        /// </summary>
        private readonly int toDisplayCount;
        /// <summary>
        /// URL连接模式
        /// </summary>
        private readonly string pagelink;
        /// <summary>
        /// 分页关键字
        /// </summary>
        private const string pageKey = "page";
        /// <summary>
        /// 页码替代变量
        /// </summary>
        private static string pagePattern = int.MaxValue.ToString();

        #endregion

        #region 构造函数
        /// <summary>
        /// 
        /// </summary>
        /// <param name="viewContext"></param>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <param name="toDisplayCount"></param>
        public RenderPager(ViewContext viewContext, int currentPage, int pageSize, int totalCount, int toDisplayCount)
        {
            this.viewContext = viewContext;
            this.currentPage = currentPage;
            this.pageSize = pageSize;
            this.totalCount = totalCount;
            this.toDisplayCount = toDisplayCount;

            this.pagelink = MvcUrlHelper.SetUrlKeyValue(viewContext.HttpContext.Request.Url.PathAndQuery, pageKey, pagePattern);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="viewContext"></param>
        /// <param name="currentPage"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalCount"></param>
        /// <param name="toDisplayCount"></param>
        /// <param name="routeValues"></param>
        public RenderPager(ViewContext viewContext, int currentPage, int pageSize, int totalCount, int toDisplayCount, object routeValues)
        {
            this.viewContext = viewContext;
            this.currentPage = currentPage;
            this.pageSize = pageSize;
            this.totalCount = totalCount;
            this.toDisplayCount = toDisplayCount;

            RouteValueDictionary dictionary = new RouteValueDictionary(viewContext.RouteData.Values);
            RouteValueDictionary tmp = routeValues == null ? new RouteValueDictionary() : new RouteValueDictionary(routeValues);
            UrlHelper url = new UrlHelper(viewContext.RequestContext);
            foreach (KeyValuePair<string, object> pair in tmp)
            {
                dictionary[pair.Key] = pair.Value;
            }

            dictionary[pageKey] = pagePattern;
            this.pagelink = url.RouteUrl(dictionary);

            if (viewContext.HttpContext.Request.QueryString.Count > 0)
            {
                this.pagelink = string.Concat(this.pagelink, "?", viewContext.HttpContext.Request.QueryString);
            }
        }

        #endregion

        #region 方法
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public string RenderHTML()
        {
            if (totalCount <= pageSize)
                return string.Empty;

            //总页数
            int pageCount = (int)Math.Ceiling(this.totalCount / (double)this.pageSize);

            //起始页
            int start = 1;

            //结束页
            int end = toDisplayCount;
            if (pageCount < toDisplayCount) end = pageCount;

            //中间值
            int centerNumber = toDisplayCount / 2;

            if (pageCount > toDisplayCount)
            {

                //显示的第一位
                int topNumber = currentPage - centerNumber;

                if (topNumber > 1)
                {
                    start = topNumber;
                }

                if (topNumber > pageCount - toDisplayCount)
                {
                    start = pageCount - toDisplayCount + 1;
                }

                //显示的最后一位
                int endNumber = currentPage + centerNumber;

                if (currentPage >= pageCount - centerNumber)
                {
                    end = pageCount;
                }
                else
                {
                    if (endNumber > toDisplayCount)
                    {
                        end = endNumber;
                    }
                }
            }

            StringBuilder sb = new StringBuilder();

            //Previous
            if (this.currentPage > 1)
            {
                sb.Append(GeneratePageLink("&lt;&nbsp;Prev", this.currentPage - 1));
            }

            if (start > 1)
            {
                sb.Append(GeneratePageLink("1", 1));
                sb.Append("..");
            }

            //end Previous

            for (int i = start; i <= end; i++)
            {
                if (i == this.currentPage)
                {
                    sb.AppendFormat("<span class=\"current\">{0}</span>", i);
                }
                else
                {
                    sb.Append(GeneratePageLink(i.ToString(), i));
                }
            }

            //Next
            if (end < pageCount)
            {
                sb.Append("..");
                sb.Append(GeneratePageLink(pageCount.ToString(), pageCount));
            }

            if (this.currentPage < pageCount)
            {
                sb.Append(GeneratePageLink("Next&nbsp;&gt;", this.currentPage + 1));
            }
            //end Next

            sb.Append("<span><input type=\"text\" class=\"pagerInput\" maxlength=\"5\" title=\"输入数字后请直接按回车跳转\" onpaste=\"return false;\"" + 
                " onkeydown=\"if(event.keyCode==13&&!isNaN(parseInt(this.value)))" + 
                "   window.location='" + this.pagelink + "'.replace('" + pagePattern + "', this.value);" +
                " return (event.keyCode==8||event.keyCode==46||(event.keyCode>=48&&event.keyCode<=57)||(event.keyCode>=96&&event.keyCode<=105))\"/></span>");

            return sb.ToString();
        }

        /// <summary>
        /// 生成Page的链接
        /// </summary>
        /// <param name="linkText">文字</param>
        /// <param name="PageNumber">页码</param>
        /// <returns></returns>
        private string GeneratePageLink(string linkText, int PageNumber)
        {
            string linkFormat = string.Format("<a href=\"{0}\">{1}</a>", this.pagelink.Replace(pagePattern, PageNumber.ToString()), linkText);
            return linkFormat;
        }
        #endregion
    }
}